<template>
  <el-card class="search_wrap">
    <el-form ref="formRef" :model="form" label-width="100px">
      <el-row>
        <template v-for="(item, index) in search">
          <el-col
            :class="
              isCollpase && index > hideOtherInput ? 'form_item_hidden' : ''
            "
            :span="spans"
          >
            <el-form-item :label="item.label" :prop="item.prop">
              <template v-if="item.type == 'select'">
                <el-select
                  style="width: 100%"
                  :filterable="item.filter"
                  :remote="item.filter"
                  :placeholder="
                    item.filter ? `请输入${item.label}` : `请选择${item.label}`
                  "
                  clearable
                  reserve-keyword
                  v-model="form[`${item.prop}`]"
                  :remote-method="
                    item.remoteMethods ? (query:string) => debounce(remoteMethod(query,item),200) : debounce((query:string) => innerRemoteMethod(query,item.prop!),200)
                  "
                  :loading="searchLoading"
                >
                  <template v-for="e in item.valueEnum ?? filterReture">
                    <el-option :label="e.value" :value="e.key">
                      <div v-html="e.highValue ?? e.value"></div>
                    </el-option>
                  </template>
                </el-select>
              </template>
              <template
                v-else-if="
                  item.type == 'datepicker' ||
                  item.type == 'datetimerange' ||
                  item.type == 'datetime'
                "
              >
                <el-date-picker
                  v-model="form[`${item.prop}`]"
                  :type="item.type"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  :value-format="
                    item.type != 'datepicker' ? 'YYYY-MM-DD HH:mm:ss' : ''
                  "
                  :default-time="item.defaultTime"
                />
              </template>
              <el-input
                v-model.trim="form[`${item.prop}`]"
                :maxlength="item.maxlength"
                v-else
                :placeholder="`请输入${item.label}`"
              />
            </el-form-item>
          </el-col>
        </template>
        <el-form-item class="btn_search" v-if="search">
          <el-button :loading="loading" @click="onsubmit" type="primary"
            >查询</el-button
          >
          <el-button :loading="loading" @click="onreset">重置</el-button>
          <el-button
            v-if="!isCollpase && isShowIcon"
            link
            @click="onCollpase"
            type="primary"
            >收起 <Icons style="margin-left: 5px" name="ArrowUp"
          /></el-button>
          <el-button
            v-if="isCollpase && isShowIcon"
            link
            @click="onCollpase"
            type="primary"
            >展开 <Icons style="margin-left: 5px" name="ArrowDown"
          /></el-button>
        </el-form-item>
      </el-row>
    </el-form>
  </el-card>
</template>

<script lang="ts" setup>
import { ZCTableOption } from "@/model/zcTable";
import debounce from "@/utils/debounce";
import { FormInstance } from "element-plus";
import { $, $ref } from "vue/macros";

const emit = defineEmits<{ (e: "changeData", data: any): void }>();
const props = defineProps<{
  search?: ZCTableOption[];
  isCollpase?: boolean;
  loading?: boolean;
  request?: any;
}>();
let formRef = ref<FormInstance>();
// 筛选结果l
let filterReture = reactive<any>([]);

// 搜索栏表单初始化数据
let formDataInit: any = {};
props.search?.map((item) => {
  if (item.prop && item.show != false) {
    formDataInit[item.prop] = "";
  }
});
let form = reactive(formDataInit);

// 搜索loading
let searchLoading = ref(false);
// 收起展开
let isCollpase = $ref(props.isCollpase || false);
// 隐藏大于此的input
let hideOtherInput: number = $ref(0);
// span占比
let spans = $ref<number>(8);
// 去除空值
const delEmpty = (e: any) => {
  for (const key in e) {
    if (Object.hasOwnProperty.call(e, key)) {
      const ele = e[key];
      if (ele === "") {
        delete e[key];
      } else {
        if (Object.prototype.toString.call(ele) === "[object Object]") {
          if (JSON.stringify(ele) == "{}") {
            delete e[key];
          }
        }
      }
    }
  }
  return e;
};
const unique = (arr: string[]) => {
  return Array.from(new Set(arr));
};
//模糊查询
const innerRemoteMethod = async (query: string, prop: string) => {
  const res = await props.request({ pageSize: -1 });
  const getNames = res.map((item: any) => {
    return item?.[prop];
  });
  const uniqueArr = unique(getNames).map((item) => {
    return { value: item, key: item };
  });
  filterArr(uniqueArr, query);
};
// 查询
const onsubmit = () => {
  const handleForm = delEmpty(form);
  if (JSON.stringify(handleForm) == "{}") return;

  emit("changeData", handleForm);
};
// 重置
const onreset = () => {
  formRef.value?.resetFields();
  emit("changeData", delEmpty(form));
};
// 收起
const onCollpase = () => {
  isCollpase = !isCollpase;
};
// 收起展开是否隐藏
const isShowIcon = computed(() => {
  return !props.search ? false : hideOtherInput + 1 < props.search!.length;
});
const handleWidth = () => {
  const clientWidth = document.body.clientWidth;
  if (clientWidth > 1300) {
    hideOtherInput = 2;
    spans = 6;
  } else if (clientWidth <= 900 && clientWidth > 620) {
    hideOtherInput = 0;
    spans = 12;
  } else if (document.body.clientWidth <= 620) {
    spans = 24;
  } else {
    hideOtherInput = 1;
    spans = 8;
  }
};
watchEffect(() => {
  handleWidth();
});
// 监听页面变化
window.addEventListener("resize", () => {
  handleWidth();
});

onUnmounted(() => {
  window.removeEventListener("resize", handleWidth);
});
// 高亮
const setHighLight = (arr: any[], query: any) => {
  if (arr && arr.length > 0 && query) {
    arr = arr.map((item) => {
      let reg = new RegExp(query, "g");
      let replaceString = `<span class='high'>${query.trim()}</span>`;
      if (item.value.match(reg)) {
        item.highValue = item.value.replace(reg, replaceString);
        return item;
      }
    });
  }
};
onMounted(() => {
  props.search?.map((item) => {
    if (item?.maxlength && item?.type == "select") {
      const input = document.querySelector(".el-input__wrapper input");
      input?.setAttribute("maxlength", item?.maxlength.toString());
    }
  });
});
// 筛选搜索的数组
const filterArr = (arr: any, query: string) => {
  filterReture.length = 0;
  if (Object.prototype.toString.call(arr) == "[object Array]" && query) {
    const filterMap = arr.filter((item: any) => {
      return item.value.includes(query);
    });
    setHighLight(filterMap, query);
    filterReture.push(...filterMap);
  }
};
// 搜索
const remoteMethod = (query: string, item: ZCTableOption) => {
  if (query) {
    searchLoading.value = true;
    item.remoteMethods &&
      item
        ?.remoteMethods()
        .then((res) => {
          filterArr(res, query);
        })
        .finally(() => {
          searchLoading.value = false;
        });
  } else {
    filterReture.length = 0;
  }
};
</script>

<style lang="scss">
.search_wrap {
  .el-form-item {
    margin-bottom: 0;
  }
  .el-row {
    row-gap: 24px;
  }
}
.high {
  color: var(--el-color-primary);
}
.btn_search {
  flex: 1;
  .el-form-item__content {
    justify-content: end !important;
    margin-left: 0 !important;
  }
}
:where(.form_item_hidden) {
  display: none;
}
</style>
